package com.k4rthik.clipall.clipb;

import com.k4rthik.clipall.commons.Level;
import com.k4rthik.clipall.commons.Logger;
import com.k4rthik.clipall.network.NetworkOps;

import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.Transferable;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * Created by IntelliJ IDEA.
 * User: k4rthik
 * Date: 3/25/12
 * Time: 1:14 PM
 */

public class OwnershipClipboardListener extends Thread implements ClipboardOwner
{
    private Clipboard clipB = Toolkit.getDefaultToolkit().getSystemClipboard();
    private static int worstOwnerChangeDelay = 20;

    private OutputStream clipboardLog;

    @Override
    public void run()
    {
        SecurityManager securityManager = System.getSecurityManager();

        if (securityManager != null) {
            try {
                securityManager.checkSystemClipboardAccess();
            } catch (Exception e) {
                Logger.log("Program cannot access System clipboard. Exiting.", Level.FATAL);
                System.exit(1);
            }
        }

        try
        {
            clipboardLog = new FileOutputStream("clipBLogs.txt");
        } catch (FileNotFoundException e) {
            Logger.log(e.getMessage(), Level.WARN);
            clipboardLog = null;
        }

        this.startListener();
    }

    private void startListener()
    {
        try
        {
            sleep(worstOwnerChangeDelay);
            Transferable cbContents = clipB.getContents(null);
            regainOwnership(cbContents);

            Logger.log("Connecting to Clipboard OK. Current clipboard contents: ", Level.INFO);
            Logger.log(ClipOps.getClipboardText(clipB));

            Logger.log("Listening to clipboard...");

            long startTime = System.currentTimeMillis();
            while((System.currentTimeMillis() - startTime) >= 0)
            { }
        } catch(InterruptedException e) {
            Logger.log("Failed to initialize Clipboard Listener instance", e);
            increaseDelay();
        }
    }

    @Override
    public void lostOwnership(Clipboard clipboard, Transferable transferable)
    {
        try {
            Logger.log("New clipboard contents:\n"+ClipOps.getClipboardText(clipB), Level.INFO);
            clipboardLog.write(("New clipboard contents:\n"+ClipOps.getClipboardText(clipB)+"\n").getBytes());

            sleep(worstOwnerChangeDelay);
            regainOwnership();
        } catch (Exception e) {
            Logger.log("Failed to process new clipboard contents", Level.ERROR);
            e.printStackTrace();
            increaseDelay();
        }
    }

    public synchronized void regainOwnership()
    {
        clipB.setContents(clipB.getContents(null), this);

        try {
            NetworkOps.sendClipboardText(ClipOps.getClipboardText(clipB));
        } catch (IOException e) {
            Logger.log("Unable to send clipboard data over network", e);
        }

    }

    public void regainOwnership(Transferable transferable)
    {
        clipB.setContents(transferable, this);
    }

    public static synchronized void increaseDelay()
    {
        worstOwnerChangeDelay += 10;
    }
}